import grpc
from functools import wraps
import traceback
import logging

logger = logging.getLogger(__name__)

class GlobalExceptionInterceptor(grpc.ServerInterceptor):
    """gRPC全局异常拦截器"""
    
    def __init__(self):
        self._terminator = self._create_terminator()
    
    def intercept_service(self, continuation, handler_call_details):
        """拦截服务调用"""
        handler = continuation(handler_call_details)
        if handler is None:
            return handler
            
        if handler.request_streaming or handler.response_streaming:
            return handler
            
        return grpc.unary_unary_rpc_method_handler(
            self._wrap_handler(handler.unary_unary),
            request_deserializer=handler.request_deserializer,
            response_serializer=handler.response_serializer
        )
    
    def _wrap_handler(self, original_handler):
        """包装原始处理器"""
        @wraps(original_handler)
        def wrapper(request, context):
            try:
                return original_handler(request, context)
            except Exception as e:
                self._handle_exception(e, context)
                return None
        return wrapper
    
    def _handle_exception(self, exception, context):
        """统一异常处理"""
        logger.error(f"gRPC服务异常: {str(exception)}")
        logger.error(traceback.format_exc())
        
        # 根据异常类型设置不同的状态码
        if isinstance(exception, ValueError):
            context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
            context.set_details(str(exception))
        elif isinstance(exception, KeyError):
            context.set_code(grpc.StatusCode.NOT_FOUND)
            context.set_details("资源未找到")
        elif "validation" in str(exception).lower():
            context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
            context.set_details("参数验证失败")
        else:
            context.set_code(grpc.StatusCode.INTERNAL)
            context.set_details("服务器内部错误")
    
    def _create_terminator(self):
        """创建终止器"""
        def terminator(request, context):
            context.set_code(grpc.StatusCode.INTERNAL)
            context.set_details("请求被终止")
            return None
        return terminator

class ExceptionHandlerMixin:
    """异常处理混入类，用于简化服务实现"""
    
    def _handle_grpc_exception(self, context, exception):
        """统一的异常处理方法"""
        if isinstance(exception, ValueError):
            context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
            context.set_details(str(exception))
        elif isinstance(exception, KeyError):
            context.set_code(grpc.StatusCode.NOT_FOUND)
            context.set_details("资源未找到")
        elif hasattr(exception, 'code') and hasattr(exception, 'message'):
            context.set_code(exception.code)
            context.set_details(exception.message)
        else:
            context.set_code(grpc.StatusCode.INTERNAL)
            context.set_details("服务器内部错误")
            
        return None

class gRPCException(Exception):
    """自定义gRPC异常基类"""
    
    def __init__(self, code, message):
        self.code = code
        self.message = message
        super().__init__(message)

class ValidationException(gRPCException):
    """参数验证异常"""
    
    def __init__(self, message):
        super().__init__(grpc.StatusCode.INVALID_ARGUMENT, message)

class NotFoundException(gRPCException):
    """资源未找到异常"""
    
    def __init__(self, message="资源未找到"):
        super().__init__(grpc.StatusCode.NOT_FOUND, message)

class BusinessException(gRPCException):
    """业务异常"""
    
    def __init__(self, message):
        super().__init__(grpc.StatusCode.FAILED_PRECONDITION, message)